﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace AndroidADBTool
{
    public partial class Form1 : Form
    {
        private LoadingHelper loading = new LoadingHelper();
        public Form1()
        {
            InitializeComponent();
        }

        private List<string> DevicesList = new List<string>();
        private void Form1_Load(object sender, EventArgs e)
        {
            button_devices_Click(null, null);
        }

        private void button_devices_Click(object sender, EventArgs e)
        {
            try
            {
                loading.ShowLoadingScreen();
                richTextBox1.Text = "";
                DevicesList = GetDevices();
                checkedListBox_devices.Items.Clear();
                foreach (var item in DevicesList)
                {
                    checkedListBox_devices.Items.Add(item.Split('\t')[0]);
                }
                button_all.Text = "全选";
                allchecked = false;
            }
            catch (Exception)
            {
                throw;
            }
            finally
            {
                loading.CloseForm();
            }
        }

        private void button_disconnect_Click(object sender, EventArgs e)
        {
            try
            {
                loading.ShowLoadingScreen();
                foreach (string item in checkedListBox_devices.CheckedItems)
                {
                    DisConnect(item);
                }
                button_devices_Click(null, null);
            }
            catch (Exception)
            {
                throw;
            }
            finally
            {
                loading.CloseForm();
            }
           
        }

        private void button_connect_Click(object sender, EventArgs e)
        {
            try
            {
                loading.ShowLoadingScreen();
                string ip = textBox_ip.Text;
                int port = Convert.ToInt32(textBox_port.Text);
                Connect(ip, port);
                button_devices_Click(null, null);
            }
            catch (Exception)
            {
                throw;
            }
            finally
            {
                loading.CloseForm();
            }
           
        }

        private void Form1_FormClosed(object sender, FormClosedEventArgs e)
        {
            string output = RunCmd("kill-server");
            Invoke(new Action(() =>
            {
                richTextBox1.Text = output;
            }));
        }

        private void button_install_Click(object sender, EventArgs e)
        {
            try
            {
                loading.ShowLoadingScreen();
                richTextBox1.Text = "";
                string path = textBox_apk.Text;
                Invoke(new Action(() =>
                {
                    foreach (string item in checkedListBox_devices.CheckedItems)
                    {
                        InstallApk(item, path);
                    }
                }));
            }
            catch (Exception)
            {
                throw;
            }
            finally
            {
                loading.CloseForm();
            }
        }

        private void button_installsystem_Click(object sender, EventArgs e)
        {
            try
            {
                loading.ShowLoadingScreen();
                richTextBox1.Text = "";
                string path = textBox_apk.Text;
                Invoke(new Action(() =>
                {
                    foreach (string item in checkedListBox_devices.CheckedItems)
                    {
                        InstallApkToSystem(item, path);
                    }
                }));
            }
            catch (Exception)
            {
                throw;
            }
            finally
            {
                loading.CloseForm();
            }
        }
        private void button_getPackage_Click(object sender, EventArgs e)
        {
            try
            {
                loading.ShowLoadingScreen();
                richTextBox1.Text = "";
                comboBox_pack.Items.Clear();
                Invoke(new Action(() =>
                {
                    foreach (string item in checkedListBox_devices.CheckedItems)
                    {
                        var packages = GetThirdPackage(item);
                        foreach (var itempack in packages)
                        {
                            string pack = itempack.Substring(itempack.IndexOf('=') + 1).TrimEnd();
                            if (!comboBox_pack.Items.Contains(pack))
                            {
                                comboBox_pack.Items.Add(pack);
                            }
                        }
                    }
                }));
            }
            catch (Exception)
            {
                throw;
            }
            finally
            {
                loading.CloseForm();
            }
        }

        private void button_Uninstall_Click(object sender, EventArgs e)
        {
            try
            {
                loading.ShowLoadingScreen();
                richTextBox1.Text = "";
                if (!string.IsNullOrWhiteSpace(comboBox_pack.Text))
                {
                    string pack = comboBox_pack.Text;
                    Invoke(new Action(() =>
                    {
                        foreach (string item in checkedListBox_devices.CheckedItems)
                        {
                            UnInstallPackage(item, pack);
                        }
                    }));
                }
            }
            catch (Exception)
            {
                throw;
            }
            finally
            {
                loading.CloseForm();
            }
        }

        private void button_open_Click(object sender, EventArgs e)
        {
            OpenFileDialog open = new OpenFileDialog();
            open.Filter = "apk|*.apk";
            if (open.ShowDialog() == DialogResult.OK)
            {
                string saveFileName = open.FileName;
                textBox_apk.Text = saveFileName;
            }
        }

        private bool allchecked = false;
        private void button_all_Click(object sender, EventArgs e)
        {
            allchecked = !allchecked;
            for (int i = 0; i < checkedListBox_devices.Items.Count; i++)
            {
                checkedListBox_devices.SetItemChecked(i, allchecked);
            }
            if (allchecked)
            {
                button_all.Text = "全不选";
            }
            else
            {
                button_all.Text = "全选";
            }
        }

        private void button_openadb_Click(object sender, EventArgs e)
        {
            try
            {
                loading.ShowLoadingScreen();
                richTextBox1.Text = "";
                Invoke(new Action(() =>
                {
                    foreach (string item in checkedListBox_devices.CheckedItems)
                    {
                        OpenAdbd(item);
                    }
                }));
            }
            catch (Exception)
            {
                throw;
            }
            finally
            {
                loading.CloseForm();
            }
        }

        private void button_reboot_Click(object sender, EventArgs e)
        {
            try
            {
                loading.ShowLoadingScreen();
                richTextBox1.Text = "";
                Invoke(new Action(() =>
                {
                    foreach (string item in checkedListBox_devices.CheckedItems)
                    {
                        string output = RunCmd($"-s {item} shell am restart");
                        Invoke(new Action(() =>
                        {
                            richTextBox1.AppendText(output + Environment.NewLine);
                        }));
                    }
                }));
            }
            catch (Exception)
            {
                throw;
            }
            finally
            {
                loading.CloseForm();
            }
           
        }


        private void button_Cmd_Click(object sender, EventArgs e)
        {
            try
            {
                loading.ShowLoadingScreen();
                richTextBox1.Text = "";
                if (!string.IsNullOrWhiteSpace(textBox_cmd.Text))
                {
                    Invoke(new Action(() =>
                    {
                        foreach (string item in checkedListBox_devices.CheckedItems)
                        {
                            string output = RunCmd($"-s {item} {textBox_cmd.Text}");
                            Invoke(new Action(() =>
                            {
                                richTextBox1.AppendText(output + Environment.NewLine);
                            }));
                        }
                    }));
                }
            }
            catch (Exception)
            {
                throw;
            }
            finally
            {
                loading.CloseForm();
            }
           
        }

        private void button_stop_Click(object sender, EventArgs e)
        {
            try
            {
                loading.ShowLoadingScreen();
                richTextBox1.Text = "";
                if (!string.IsNullOrWhiteSpace(comboBox_pack.Text))
                {
                    Invoke(new Action(() =>
                    {
                        foreach (string item in checkedListBox_devices.CheckedItems)
                        {
                            string output = RunCmd($"-s {item} shell am force-stop {comboBox_pack.Text}");
                            Invoke(new Action(() =>
                            {
                                richTextBox1.AppendText(output + Environment.NewLine);
                            }));
                        }
                    }));
                }
            }
            catch (Exception)
            {
                throw;
            }
            finally
            {
                loading.CloseForm();
            }
        }

        private void button_changeboot_Click(object sender, EventArgs e)
        {
            try
            {
                loading.ShowLoadingScreen();
                richTextBox1.Text = "";
                Invoke(new Action(() =>
                {
                    foreach (string item in checkedListBox_devices.CheckedItems)
                    {
                        ChangeBootFlash(item,false);
                    }
                }));
            }
            catch (Exception)
            {
                throw;
            }
            finally
            {
                loading.CloseForm();
            }
        }

        private void button_rebootflash_Click(object sender, EventArgs e)
        {
            try
            {
                loading.ShowLoadingScreen();
                richTextBox1.Text = "";
                Invoke(new Action(() =>
                {
                    foreach (string item in checkedListBox_devices.CheckedItems)
                    {
                        ChangeBootFlash(item, true);
                    }
                }));
            }
            catch (Exception)
            {
                throw;
            }
            finally
            {
                loading.CloseForm();
            }
        }
        public void Connect(string ip, int port)
        {
            string output = RunCmd($"connect {ip}:{port}");
            Invoke(new Action(() =>
            {
                //richTextBox1.AppendText(output + Environment.NewLine);
            }));
        }

        public void Connect(string host)
        {
            string output = RunCmd($"connect {host}");
            Invoke(new Action(() =>
            {
                //richTextBox1.AppendText(output + Environment.NewLine);
            }));
        }

        public void DisConnect(string host)
        {
            string output = RunCmd($"disconnect {host}");
            Invoke(new Action(() =>
            {
                //richTextBox1.AppendText(output + Environment.NewLine);
            }));
        }

        public List<string> GetDevices(bool showmsg = true)
        {
            List<string> list = new List<string>();
            string output = RunCmd("devices");
            Invoke(new Action(() =>
            {
                if (showmsg)
                {
                    richTextBox1.AppendText(output + Environment.NewLine);
                }

                string str = "List of devices attached";
                output = output.Substring(output.IndexOf(str));
                string[] sp = { "\r\n" };
                list = output.Split(sp, StringSplitOptions.RemoveEmptyEntries).ToList();
                list.Remove(str);

            }));
            return list;
        }

        public void InstallApk(string host, string apkfile)
        {
            string adbPath = Application.StartupPath + @"\adb\aapt.exe";
            string fileoutput = RunCmd(adbPath, $@"dump badging ""{apkfile}""");
            string package = "";
            string activity = "";
            Invoke(new Action(() =>
            {
                string str_1 = "package: name=";
                var temp1= fileoutput.Substring(fileoutput.IndexOf(str_1) + str_1.Length);
                string temp2 = temp1.Substring(0, temp1.IndexOf("versionCode=")).TrimEnd();
                package = temp2.Replace("'", "");
                string str = "launchable-activity: name=";
                var str1=fileoutput.Substring(fileoutput.IndexOf(str) + str.Length);
                var str2=str1.Substring(0, str1.IndexOf("label=")).TrimEnd().Replace("'", "");
                activity = str2.Replace(package, "");
                //richTextBox1.AppendText(fileoutput + Environment.NewLine);
            }));
            string output = RunCmd($@"-s {host} install -r ""{apkfile}""");
            Invoke(new Action(() =>
            {
                richTextBox1.AppendText(output + Environment.NewLine);
            }));
            output = RunCmd($@"-s {host} shell am start {package}/{activity}");
            Invoke(new Action(() =>
            {
                richTextBox1.AppendText(output + Environment.NewLine);
            }));
        }

        public void InstallApkToSystem(string host, string apkfile)
        {
            string output = RunCmd($"-s {host} root");
            Invoke(new Action(() =>
            {
                richTextBox1.AppendText(output + Environment.NewLine);
            }));
            output = RunCmd($"-s {host} remount");
            Invoke(new Action(() =>
            {
                richTextBox1.AppendText(output + Environment.NewLine);
            }));
            output = RunCmd($@"-s {host} push ""{apkfile}"" /system/app");
            Invoke(new Action(() =>
            {
                richTextBox1.AppendText(output + Environment.NewLine);
            }));
        }

        public void UnInstallPackage(string host, string packagename, bool keepdata = false)
        {
            string k = keepdata ? "-k" : "";
            string output = RunCmd($"-s {host} uninstall {k} {packagename}");
            Invoke(new Action(() =>
            {
                richTextBox1.AppendText(output + Environment.NewLine);
            }));
        }

        public void OpenAdbd(string host)
        {
            string output = RunCmd($"-s {host} root");
            Invoke(new Action(() =>
            {
                richTextBox1.AppendText(output + Environment.NewLine);
            }));
            output = RunCmd($"-s {host} remount");
            Invoke(new Action(() =>
            {
                richTextBox1.AppendText(output + Environment.NewLine);
            }));
            output = RunCmd($@"-s {host} pull /system/build.prop ""{Application.StartupPath}""");
            Invoke(new Action(() =>
            {
                richTextBox1.AppendText(output + Environment.NewLine);
            }));
            string file = Application.StartupPath + "\\build.prop";
            var lines = File.ReadLines(file, System.Text.Encoding.UTF8).ToList();
            if (!lines.Exists(x => x.Contains("service.adb.tcp.port")))
            {
                lines.Add("service.adb.tcp.port=5555");
            }
            File.WriteAllLines(file, lines, System.Text.Encoding.UTF8);
            output = RunCmd($@"-s {host} push ""{file}"" /system");
            Invoke(new Action(() =>
            {
                richTextBox1.AppendText(output + Environment.NewLine);
            }));
            output = RunCmd($@"-s {host} tcpip 5555");
            Invoke(new Action(() =>
            {
                richTextBox1.AppendText(output + Environment.NewLine);
            }));
            output = RunCmd($"-s {host} shell am restart");
            Invoke(new Action(() =>
            {
                richTextBox1.AppendText(output + Environment.NewLine);
            }));
        }
        /// <summary>
        /// 更换开机动画
        /// </summary>
        /// <param name="host"></param>
        ///<param name="reduction">是否还原</param>
        public void ChangeBootFlash(string host,bool reduction)
        {
            string output = RunCmd($"-s {host} root");
            Invoke(new Action(() =>
            {
                richTextBox1.AppendText(output + Environment.NewLine);
            }));
            output = RunCmd($"-s {host} remount");
            Invoke(new Action(() =>
            {
                richTextBox1.AppendText(output + Environment.NewLine);
            }));
            string dpath = host.Remove(host.IndexOf(':'));
            string path = Application.StartupPath + "\\"+ dpath;
            if (!Directory.Exists(path))
            {
                Directory.CreateDirectory(path);
            }
            output = RunCmd($@"-s {host} pull /system/media/bootanimation.zip ""{path}""");
            Invoke(new Action(() =>
            {
                richTextBox1.AppendText(output + Environment.NewLine);
            }));
            if(reduction)
            {
                string file = Application.StartupPath + "\\bootanimation.zip";
                output = RunCmd($@"-s {host} shell rm /system/media/bootanimation.zip");
                Invoke(new Action(() =>
                {
                    richTextBox1.AppendText(output + Environment.NewLine);
                }));
            }
            else
            {
                string file = Application.StartupPath + "\\bootanimation.zip";
                output = RunCmd($@"-s {host} push ""{file}"" /system/media/bootanimation.zip");
                Invoke(new Action(() =>
                {
                    richTextBox1.AppendText(output + Environment.NewLine);
                }));
            }
            output = RunCmd($"-s {host} shell am restart");
            Invoke(new Action(() =>
            {
                richTextBox1.AppendText(output + Environment.NewLine);
            }));
        }

        public List<string> GetThirdPackage(string host)
        {
            List<string> list = new List<string>();
            string output = RunCmd($"-s {host} shell pm list packages -3");
            Invoke(new Action(() =>
            {
                richTextBox1.AppendText(output + Environment.NewLine);
                string str = "package:";
                if (output.IndexOf(str) != -1)
                {
                    output = output.Substring(output.IndexOf(str));
                    string[] sp = { str };
                    list = output.Split(sp, StringSplitOptions.RemoveEmptyEntries).ToList();
                    list.Remove(str);
                }
            }));
            return list;
        }

        public void KillAdb()
        {
            RunCmd("kill-server");
        }
        
        private string RunCmd(string cmdStr)
        {
            string adbPath = Application.StartupPath + @"\adb\adb.exe";
            string output = RunCmd(adbPath, cmdStr);
            return output;
        }


        private string RunCmd(string cmdExe, string cmdStr)
        {
            string output = "";
            try
            {
                using (Process p = new Process())
                {
                    p.StartInfo.FileName = "cmd.exe";
                    p.StartInfo.UseShellExecute = false; //不启用shell启动进程
                    p.StartInfo.RedirectStandardInput = true; // 重定向输入
                    p.StartInfo.RedirectStandardOutput = true; // 重定向标准输出
                    p.StartInfo.RedirectStandardError = true; // 重定向错误输出 
                    p.StartInfo.CreateNoWindow = true; // 不创建新窗口
                    p.Start();
                    //如果调用程序路径中有空格时，cmd命令执行失败，可以用双引号括起来 ，在这里两个引号表示一个引号（转义）
                    string str = string.Format(@"""{0}"" {1} {2}", cmdExe, cmdStr, "&exit");
                    //向cmd窗口发送输入信息
                    p.StandardInput.WriteLine(str);
                    p.StandardInput.AutoFlush = true;
                    //获取cmd窗口的输出信息
                    output = p.StandardOutput.ReadToEnd();
                    p.WaitForExit();
                }
            }
            catch (Exception)
            {
                throw;
            }
            return output;
        }

    }
}
